﻿using LxBasic;
using System;
using System.Collections.Generic;

namespace LxCore
{
    public class ConnectivitySolver
    {
        private readonly int FLAG_Inactive = -2;
        private readonly int FLAG_Active_ToBeClassified = -1;
        public ConnectivitySolver()
        {
            CheckCreate(LxSim.Sim.Mesh);
        }
        //local
        private ZoneLog[] ZonesMapping;
        protected void CheckCreate(FvMesh mesh)
        {
            ZonesMapping = new ZoneLog[mesh.Zones.Count];
            for (int i1 = 0; i1 < ZonesMapping.Length; i1++)
            {
                ZonesMapping[i1] = new ZoneLog();
            }
        }
        private void reset()
        {
            foreach (var z in ZonesMapping)
            {
                z.PoolId = FLAG_Inactive;
                z.ConnectedZones.Clear();
            }
        }

        private bool addFlag<T1, T2>(Func<ZoneCFDFields, T1> getEquation, Func<JointCFDFields, T2> getConnect) where T1 : ZoneHead where T2 : JointHead
        {
            int activeCount = 0;
            foreach (var zf in LxSim.Sim.Fields.ZoneFields)
            {
                if (getEquation(zf) != null)
                {
                    ZonesMapping[zf.Zone.ID].PoolId = FLAG_Active_ToBeClassified;
                    activeCount++;
                }
            }
            if (activeCount == 0) return false;
            foreach (var cf in LxSim.Sim.Fields.JointFields)
            {
                if (getConnect(cf) != null)
                {
                    var c = cf.Joint;
                    int ozid = c.OZone.ID;
                    int nzid = c.NZone.ID;
                    if (ZonesMapping[ozid].PoolId == FLAG_Inactive || ZonesMapping[nzid].PoolId == FLAG_Inactive)
                    {
                        throw new Exception("划分连通域出错");
                    }
                    if (ozid <= nzid)
                    {
                        ZonesMapping[ozid].ConnectedZones.Add(nzid);
                    }
                    else
                    {
                        ZonesMapping[nzid].ConnectedZones.Add(ozid);
                    }

                }
            }
            return true;
        }
        private int classify()
        {
            int poolCount = 0;
            foreach (var z in ZonesMapping)//遍历zoneMirror更能保证从小到大遍历
            {
                if (z.PoolId == FLAG_Inactive) continue;
                if (z.PoolId == FLAG_Active_ToBeClassified)//如果待标记，需要先标记id
                {
                    z.PoolId = poolCount;
                    poolCount++;
                }
                foreach (var zc in z.ConnectedZones)//与本zone相连的均连通
                {
                    ZonesMapping[zc].PoolId = z.PoolId;
                }
            }
            return poolCount;
        }
        public List<Pool<T1, T2>> GetConnectivity<T1, T2>(Func<ZoneCFDFields, T1> getEquation, Func<JointCFDFields, T2> getConnect) where T1 : ZoneHead where T2 : JointHead
        {
            reset();
            if (!addFlag(getEquation, getConnect))
            {
                return new(0);
            }
            int poolCount = classify();
            List<Pool<T1, T2>> pools = new(poolCount);
            for (int i1 = 0; i1 < poolCount; i1++)
            {
                pools.Add(new Pool<T1, T2>());
            }
            //zone
            foreach (var zf in LxSim.Sim.Fields.ZoneFields)
            {
                var equ = getEquation(zf);
                if (equ != null)
                {
                    pools[ZonesMapping[zf.Zone.ID].PoolId].Equations.Add(equ);
                }
            }
            //joint
            foreach (var cf in LxSim.Sim.Fields.JointFields)
            {
                var con = getConnect(cf);
                if (con != null)
                {
                    pools[ZonesMapping[cf.Joint.OZone.ID].PoolId].Connects.Add(con);
                }
            }
            return pools;
        }

        public class ZoneLog
        {
            public int PoolId;//-2表示无该区域，-1表示有该区域暂时没分配到pool
            public List<int> ConnectedZones = new List<int>();//记录比自己大的连通的区域（即单向的连通），ID为Mesh中的ID
        }
        public class Pool<T1, T2>
        {
            public Pool() { }
            public List<T1> Equations = new List<T1>();
            public List<T2> Connects = new List<T2>();
        }
    }

}
//public class ConnectivitySolver
//{
//    private readonly int FLAG_Inactive = -2;
//    private readonly int FLAG_Active_ToBeClassified = -1;

//    public ConnectivitySolver()
//    {
//        CheckCreate(LxSim.Sim.Mesh);
//    }
//    public ConnectivitySolver(FvMesh mesh)
//    {
//        CheckCreate(mesh);
//    }
//    public void CheckCreate(FvMesh mesh)
//    {
//        ZonesMapping = new ZoneLog[mesh.Zones.Count];
//        for (int i1 = 0; i1 < ZonesMapping.Length; i1++)
//        {
//            ZonesMapping[i1] = new ZoneLog();
//        }
//    }
//    //local
//    private ZoneLog[] ZonesMapping;
//    private void reset()
//    {
//        foreach (var z in ZonesMapping)
//        {
//            z.PoolId = FLAG_Inactive;
//            z.ConnectedZones.Clear();
//        }
//    }

//    private void addFlag<T1, T2>(List<T1> activeZones, List<T2> activeJoints) where T1 : EquationHead where T2 : ConnectHeadBase
//    {
//        int i1 = 0;
//        foreach (var z in activeZones)
//        {
//            var log = ZonesMapping[z.Zone.ID];
//            log.PoolId = FLAG_Active_ToBeClassified;
//            i1++;
//        }
//        foreach (var cid in activeJoints)
//        {
//            var c = cid.Joint;
//            int ozid = c.OZone.ID;
//            int nzid = c.NZone.ID;
//            if (ZonesMapping[ozid].PoolId == FLAG_Inactive || ZonesMapping[nzid].PoolId == FLAG_Inactive)
//            {
//                throw new Exception("划分连通域出错");
//            }
//            if (ozid <= nzid)
//            {
//                ZonesMapping[ozid].ConnectedZones.Add(nzid);
//            }
//            else
//            {
//                ZonesMapping[nzid].ConnectedZones.Add(ozid);
//            }
//        }
//    }
//    private int classify()
//    {
//        int poolCount = 0;
//        foreach (var z in ZonesMapping)//遍历zoneMirror更能保证从小到大遍历
//        {
//            if (z.PoolId == FLAG_Inactive) continue;
//            if (z.PoolId == FLAG_Active_ToBeClassified)//发现新pool创建新id
//            {
//                z.PoolId = poolCount;
//                poolCount++;
//            }
//            foreach (var zc in z.ConnectedZones)//与本zone相连的均连通
//            {
//                ZonesMapping[zc].PoolId = z.PoolId;
//            }
//        }
//        return poolCount;
//    }
//    public List<Pool<T1, T2>> GetConnectivity<T1, T2>(List<T1> activeZones, List<T2> activeJoints) where T1 : EquationHead where T2 : ConnectHeadBase
//    {
//        if (activeZones.Count == 0) return new List<Pool<T1, T2>>();
//        reset();
//        addFlag(activeZones, activeJoints);
//        int poolCount = classify();
//        List<Pool<T1, T2>> pools = new List<Pool<T1, T2>>(poolCount);
//        for (int i1 = 0; i1 < poolCount; i1++)
//        {
//            pools.Add(new Pool<T1, T2>());
//        }
//        //zone
//        foreach (var z in activeZones)
//        {
//            pools[ZonesMapping[z.Zone.ID].PoolId].Zones.Add(z);
//        }
//        //joint
//        foreach (var c in activeJoints)
//        {
//            pools[ZonesMapping[c.Joint.OZone.ID].PoolId].Joints.Add(c);
//        }
//        return pools;
//    }

//    public class ZoneLog
//    {
//        public int PoolId;//-2表示无该区域，-1表示有该区域暂时没分配到pool
//        public List<int> ConnectedZones = new List<int>();//记录比自己大的连通的区域（即单向的连通），ID为Mesh中的ID
//    }
//    public class Pool<T1, T2>
//    {
//        public List<T1> Zones { get; set; } = new List<T1>();
//        public List<T2> Joints { get; set; } = new List<T2>();
//    }
//}